package multithread.framework.annotation.factory;

import static multithread.framework.constant.XMLConfigConstant.THREAD_AFTER_TYPE;
import static multithread.framework.constant.XMLConfigConstant.THREAD_ALL_AFTER_TYPE;
import static multithread.framework.constant.XMLConfigConstant.THREAD_ALL_BEFORE_TYPE;
import static multithread.framework.constant.XMLConfigConstant.THREAD_BEFORE_TYPE;
import static multithread.framework.constant.XMLConfigConstant.THREAD_FOR_TYPE;
import static multithread.framework.constant.XMLConfigConstant.THREAD_GROUP_AFTER_TYPE;
import static multithread.framework.constant.XMLConfigConstant.THREAD_GROUP_BEFORE_TYPE;
import static multithread.framework.constant.XMLConfigConstant.THREAD_GROUP_FOR_TYPE;

import java.lang.annotation.Annotation;

import multithread.framework.annotation.ThreadAfter;
import multithread.framework.annotation.ThreadAllAfter;
import multithread.framework.annotation.ThreadAllBefore;
import multithread.framework.annotation.ThreadBefore;
import multithread.framework.annotation.ThreadFor;
import multithread.framework.annotation.ThreadGroupAfter;
import multithread.framework.annotation.ThreadGroupBefore;
import multithread.framework.annotation.ThreadGroupFor;

public class AnnotationFactory {
	//
//	private static volatile NoneThreadGroup noneThreadGroup = null;
	private static volatile ThreadGroupFor threadGroupFor = null;
	private static volatile ThreadBefore threadBefore = null;
	private static volatile ThreadAfter threadAfter = null;
	private static volatile ThreadGroupBefore threadGroupBefore = null;
	private static volatile ThreadGroupAfter threadGroupAfter = null;
	private static volatile ThreadAllBefore threadAllBefore = null;
	private static volatile ThreadAllAfter threadAllAfter = null;
	private static volatile ThreadFor threadFor = null;
	
	public static Object getAnnotationInstance(int type){
		if(type == THREAD_GROUP_FOR_TYPE){
			return getThreadGroupFor();
		}else if(type == THREAD_BEFORE_TYPE){
			return getThreadBefore();
		}else if(type == THREAD_AFTER_TYPE){
			return getThreadAfter();
		}else if(type == THREAD_GROUP_BEFORE_TYPE){
			return getThreadGroupBefore();
		}else if(type == THREAD_GROUP_AFTER_TYPE){
			return getThreadGroupAfter();
		}else if(type == THREAD_ALL_BEFORE_TYPE){
			return getThreadAllBefore();
		}else if(type == THREAD_ALL_AFTER_TYPE){
			return getThreadAllAfter();
		}else if(type == THREAD_FOR_TYPE){
			return getThreadFor();
		}else{
			return null;
		}
	}
	
	/**
	 * Create a ThreadFor based on "thread" attribute of method element
	 * @param threadCount
	 * @return ThreadFor
	 */
	public static ThreadFor createThreadFor(final int threadCount) {
		return new ThreadFor() {

			@Override
			public Class<? extends Annotation> annotationType() {
				return ThreadFor.class;
			}

			@Override
			public int value() {
				return threadCount;
			}
		};
	}
	
	/**
	 * Create a ThreadGroupFor instacne based on "name" attribute of "group" element
	 * @param groupName thread group name
	 * @return ThreadGroupFor
	 */
	public static ThreadGroupFor createThreadGroupFor(final String groupName){
		return new ThreadGroupFor() {
			
			@Override
			public Class<? extends Annotation> annotationType() {
				return ThreadGroupFor.class;
			}
			
			@Override
			public String value() {
				return groupName;
			}
		};
	}
	
	/**
	 * create a default ThreadFor
	 * @return a implementation of ThreadFor
	 */
	private static Object getThreadFor(){
		if(threadFor == null){
			synchronized(AnnotationFactory.class){
				if(threadFor == null){
					//construct an instance
					threadFor = new ThreadFor() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
						
						@Override
						public int value() {
							return 1;
						}
					};
				}
			}
		}
		return threadFor;
	}

	/**
	 * create a unitue instance of NoneThreadGroup
	 * @return NoneThreadGroup
	 */
/*	private static Object getNoneThreadGroup() {
		if(noneThreadGroup == null){
			synchronized(AnnotationFactory.class){
				if(noneThreadGroup == null){
					//construct an instance
					noneThreadGroup = new NoneThreadGroup() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
						
						@Override
						public String value() {
							return null;
						}
					};
				}
			}
		}
		return noneThreadGroup;
	}*/
	
	/**
	 * create a unitue instance of ThreadGroupFor
	 * @return ThreadGroupFor
	 */
	private static Object getThreadGroupFor() {
		if(threadGroupFor == null){
			synchronized(AnnotationFactory.class){
				if(threadGroupFor == null){
					//construct an instance
					threadGroupFor = new ThreadGroupFor() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
						
						@Override
						public String value() {
							return null;
						}
					};
				}
			}
		}
		return threadGroupFor;
	}
	
	/**
	 * create a unitue instance of ThreadBefore
	 * @return ThreadBefore
	 */
	private static Object getThreadBefore() {
		if(threadBefore == null){
			synchronized(AnnotationFactory.class){
				if(threadBefore == null){
					//construct an instance
					threadBefore = new ThreadBefore() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
					
					};
				}
			}
		}
		return threadBefore;
	}
	
	/**
	 * create a unitue instance of ThreadAfter
	 * @return ThreadAfter
	 */
	private static Object getThreadAfter() {
		if(threadAfter == null){
			synchronized(AnnotationFactory.class){
				if(threadAfter == null){
					//construct an instance
					threadAfter = new ThreadAfter() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
					
					};
				}
			}
		}
		return threadAfter;
	}
	
	/**
	 * create a unitue instance of ThreadGroupBefore
	 * @return ThreadGroupBefore
	 */
	private static Object getThreadGroupBefore() {
		if(threadGroupBefore == null){
			synchronized(AnnotationFactory.class){
				if(threadGroupBefore == null){
					//construct an instance
					threadGroupBefore = new ThreadGroupBefore() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
					
					};
				}
			}
		}
		return threadGroupBefore;
	}
	
	/**
	 * create a unitue instance of ThreadGroupAfter
	 * @return ThreadGroupAfter
	 */
	private static Object getThreadGroupAfter() {
		if(threadGroupAfter == null){
			synchronized(AnnotationFactory.class){
				if(threadGroupAfter == null){
					//construct an instance
					threadGroupAfter = new ThreadGroupAfter() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
					
					};
				}
			}
		}
		return threadGroupAfter;
	}
	
	/**
	 * create a unitue instance of ThreadAllBefore
	 * @return ThreadAllBefore
	 */
	private static Object getThreadAllBefore() {
		if(threadAllBefore == null){
			synchronized(AnnotationFactory.class){
				if(threadAllBefore == null){
					//construct an instance
					threadAllBefore = new ThreadAllBefore() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
					
					};
				}
			}
		}
		return threadAllBefore;
	}
	
	/**
	 * create a unitue instance of ThreadAllAfter
	 * @return ThreadAllAfter
	 */
	private static Object getThreadAllAfter() {
		if(threadAllAfter == null){
			synchronized(AnnotationFactory.class){
				if(threadAllAfter == null){
					//construct an instance
					threadAllAfter = new ThreadAllAfter() {
						
						@Override
						public Class<? extends Annotation> annotationType() {
							return null;
						}
					
					};
				}
			}
		}
		return threadAllAfter;
	}
	
}
